package edu.mit.nice;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import edu.mit.nice.message.JoinLayerMessage;
import edu.mit.nice.message.JoinLayerReplyMessage;
import edu.mit.nice.message.Message;
import edu.mit.nice.struct.Cluster;
import edu.mit.nice.struct.Node;

public class Control extends Thread
{
	private NiceClient client;
	
	private ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 5, 100, TimeUnit.MICROSECONDS, new LinkedBlockingQueue<Runnable>());
	
	public Control(NiceClient client)
	{
		this.client = client;
	}

	private void listen() throws IOException
	{
		ServerSocket server = new ServerSocket(Constants.CONTROLPORT);
		
		while(true)
		{
			System.out.println("Waiting for new connections");
			Socket s = server.accept();
			pool.execute(new NewConnectionHandler(s, client));
		}
	}
	
	public void run()
	{
		try {
			listen();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

class NewConnectionHandler implements Runnable
{
	private Socket socket;
	private NiceClient nc;
	
	public NewConnectionHandler(Socket dp, NiceClient nc)
	{
		socket = dp;
		this.nc = nc;
	}

	public void run() 
	{
		System.out.println("New connection from " + socket.getInetAddress());
		
		try {
			ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
			ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
			
			Message message = (Message)ois.readObject();
			
			if(message instanceof JoinLayerMessage)
			{
				JoinLayerMessage jlm = (JoinLayerMessage)message;
				
				int layer = jlm.getLayer();
				
				Cluster c = nc.getTopCluster();
				
				oos.writeObject(new JoinLayerReplyMessage(c, layer));
				
				socket.close();
			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}